package com.huatech.support.shiro;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SerializationUtils;

import com.huatech.support.redis.RedisUtil;
/**
 * 
 * @author lh@erongdu.com
 * @since 2019-01-28
 *
 */
public class RedisSessionDaoBak extends AbstractSessionDAO {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(RedisSessionDaoBak.class);
	
	public static final String SESSION_PREFIX = "shiro_session:";
	public static final int DEFAILT_TIME_OUT = 30;
	//@Resource RedisTemplate<String, Object> redisTemplate;
	@Resource RedisUtil redisUtil;
	private int timeout = DEFAILT_TIME_OUT;
	
	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	@Override
	protected Serializable doCreate(Session session) {
		Serializable id = generateSessionId(session);
		LOGGER.debug("id:{}", id.toString());
		assignSessionId(session, id);//将session 和 sessionId捆绑在一起
		saveSession(session);
		return id;
	}
	
	public void update(Session session) throws UnknownSessionException {
		LOGGER.debug("id:{}", session.getId().toString());
		saveSession(session);
	}

	public void delete(Session session) {
		LOGGER.debug("id:{}", session.getId().toString());
		if(session == null || session.getId() == null){
			return;
		}
		redisUtil.del(getKey(session.getId()));
	}
	
	public Collection<Session> getActiveSessions() {
		 List<String> keys = redisUtil.keys(SESSION_PREFIX);
		 Set<Session> sessions = new HashSet<Session>();
		 if(keys.size() == 0){
			 return sessions;
		 }
		 for (String id : keys) {
			 Session _session = getSession(id);
			 if(_session == null){
				 continue;
			 }
//			 SimpleSession session = new SimpleSession();
//			 session.setId(id);
//			 session.setTimeout(_session.getTimeout());
//			 session.setLastAccessTime(_session.getLastAccessTime());
			 sessions.add(_session);			 
		 }		 
		return sessions;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		if(sessionId == null){
			return null;
		}
		LOGGER.debug("id:{}", sessionId.toString());
		return getSession(sessionId);
	}

	private static byte[] getKey(Serializable id){
		return (SESSION_PREFIX + id.toString()).getBytes();
	}
	
	private void saveSession(Session session){
		if(session != null && session.getId() != null){
			byte[] key = getKey(session.getId());
			byte[] value = SerializationUtils.serialize(session);
			redisUtil.set(key, value, timeout * 60);
		}		
	}
	
	private Session getSession(Serializable id){
		LOGGER.debug("id:{}", id.toString());
		byte[] value = redisUtil.get(getKey(id));
		if(value != null){
			return (Session)SerializationUtils.deserialize(value);
		}
		return null;
	}
	
//	private static String getKey(Serializable id){
//		return SESSION_PREFIX + id.toString();
//	}
//
//	private void save(Session session){
//		if(session != null && session.getId() != null){
//			Serializable id = session.getId();
//			redisTemplate.opsForValue().set(getKey(id), JSONObject.toJSONString(session), timeout, TimeUnit.MINUTES);
//			//redisTemplate.opsForHash().put(SESSION_PREFIX, getHashKey(id), JSONObject.toJSONString(session));
//		}
//	}
//	
//	private void delete(Serializable id){
//		if(id != null){
//			redisTemplate.delete(getKey(id));
//		}
//	}
//	
//	private Session get(Serializable id){
//		String sessionJson = (String)redisTemplate.boundValueOps(getKey(id)).get();
//		if(StringUtils.isNotEmpty(sessionJson)){
//			return JSONObject.parseObject(sessionJson, Session.class);
//		}
//		return null;
//	}
//	
//	private Set<String> keys(){		  
//    	return redisTemplate.execute(new RedisCallback<Set<String>>() {
//			public Set<String> doInRedis(RedisConnection connection) throws DataAccessException {
//				Set<String> binaryKeys = new HashSet<String>();
//    	        Cursor<byte[]> cursor = connection.scan( new ScanOptions.ScanOptionsBuilder().match(SESSION_PREFIX + "*").count(10000).build());
//    	        while (cursor.hasNext()) {    	        	
//    	            binaryKeys.add(new String(cursor.next()));
//    	        }
//    	        connection.close();
//    	        return binaryKeys;
//			}
//    	});    
//	}
	 
}
